/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package scores;

import entities.Betslip;
import entities.Discipline;
import entities.Game;
import entities.League;
import entities.Market;
import entities.Transact;
import entities.specificMarket;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.hibernate.classic.Session;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

public class Scores implements Runnable {

    private Session session;
    private List wynik;

    public void gamesUpdate() {

        try {
            downloadFile("http://bettingr.sportbet.com/livelines2.xml", "livelines2.xml");
            File xmlFile = new File("livelines2.xml");
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(xmlFile);
            doc.getDocumentElement().normalize();

            NodeList list = doc.getElementsByTagName("sport");

            for (int i = 0; i < list.getLength(); i++) {
                Node currentNode = list.item(i);
                if (currentNode.getAttributes().getNamedItem("type").getNodeValue().equals("SOC")) {
                    soccerGamesUpdate(currentNode);
                } else if (currentNode.getAttributes().getNamedItem("type").getNodeValue().equals("MLB")) {
                    baseballGamesUpdate(currentNode);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void scoresUpdate() {

        try {
            downloadFile("http://www.sportbet.com/BJFeed/xmlscores.aspx", "xmlscores.aspx.xml");
            File xmlFile = new File("xmlscores.aspx.xml");
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(xmlFile);
            doc.getDocumentElement().normalize();

            NodeList list = doc.getElementsByTagName("Game");

            for (int i = 0; i <
                    list.getLength(); i++) {
                Node currentNode = list.item(i);
                if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element elem = (Element) currentNode;
                    try {
                        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
                        setSession(sessionFactory.openSession());
                        Transaction tx = getSession().beginTransaction();
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        Date data = new Date(getTagValue("GameDate", elem));
                        sdf.format(data);
                        Query q = getSession().createQuery("from Game where leagueID = " + currentNode.getAttributes().getNamedItem("IdLeague").getNodeValue() +
                                " AND name = '" + getTagValue("HomeTeam", elem) + " - " + getTagValue("VisitorTeam", elem) + "' AND date = '" + sdf.format(data) + "'");
                        setWynik((ArrayList) q.list());
                        Game mecz = new Game();
                        if (!wynik.isEmpty()) {
                            mecz = (Game) wynik.get(0);
                            q =
                                    getSession().createQuery("from Market where gameID = " + mecz.getId());
                            setWynik((ArrayList) q.list());
                            Market rynek = new Market();
                            if (!wynik.isEmpty() && ((Market) wynik.get(0)).getResult().equals("n")) {
                                rynek = (Market) wynik.get(0);

                                if (Integer.parseInt(getTagValue("HomeScore", elem)) > Integer.parseInt(getTagValue("VisitorScore", elem))) {
                                    rynek.setResult("1");
                                } else if (Integer.parseInt(getTagValue("HomeScore", elem)) < Integer.parseInt(getTagValue("VisitorScore", elem))) {
                                    rynek.setResult("2");
                                } else {
                                    rynek.setResult("x");
                                }

                                getSession().update(rynek);
                                betslipsUpdate(rynek);
                                System.out.println("UPDATED: " + mecz.getName() + " " + mecz.getDate() + " " + rynek.getResult());
                            }

                        }
                        tx.commit();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    } finally {
                        getSession().close();
                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void baseballGamesUpdate(Node currentNode) {

        NodeList gameList = currentNode.getChildNodes();
        for (int j = 0; j <
                gameList.getLength(); j++) {
            Node currentGameNode = gameList.item(j);
            if (currentGameNode.getNodeType() == Node.ELEMENT_NODE) {
                Element elem = (Element) currentGameNode;
                if (!elem.getAttributes().getNamedItem("Description").getNodeValue().equals("1ST FULL 5 INNINGS STRAIGHT BETS ONLY, $500 MAX BET")) {
                    try {
                        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
                        setSession(sessionFactory.openSession());
                        Transaction tx = getSession().beginTransaction();
                        Game mecz = new Game();
                        Date data = new Date(getTagValue("date", elem));
                        mecz.setDate(data);
                        mecz.setName(getTagValue("hometeam", elem) + " - " + getTagValue("awayteam", elem));
                        Query q = getSession().createQuery("from League where name = 'MAJOR LEAGUE BASEBALL'");
                        setWynik((ArrayList) q.list());
                        mecz.setLeague((League) wynik.get(0));
                        if (getSession().createQuery(("from Game where name = '" + mecz.getName()) + "'").list().isEmpty()) {
                            getSession().save(mecz);
                            System.out.println("GAME ADDED: " + mecz.getName() + " " + mecz.getDate());
                        }

                        tx.commit();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    } finally {
                        getSession().close();
                    }

                    try {
                        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
                        setSession(sessionFactory.openSession());
                        Transaction tx = getSession().beginTransaction();
                        Market rynek = new Market();
                        Query q = getSession().createQuery("from Game where name = '" + getTagValue("hometeam", elem) + " - " + getTagValue("awayteam", elem) + "'");
                        setWynik((ArrayList) q.list());
                        rynek.setGame((Game) wynik.get(0));
                        rynek.setOdds_draw(0);
                        Double oddsAway = convertOdds(getTagValue("AwayMoneyLine", elem));
                        Double oddsHome = convertOdds(getTagValue("HomeMoneyLine", elem));
                        rynek.setOdds_away(oddsAway);
                        rynek.setOdds_home(oddsHome);
                        rynek.setResult("n");
                        q =
                                getSession().createQuery("from specificMarket where name = 'Moneyline'");
                        setWynik((ArrayList) q.list());
                        rynek.setSpecificMarket((specificMarket) wynik.get(0));
                        if (getSession().createQuery("select distinct m from Market m left join fetch m.game as g where g.id =" + rynek.getGame().getId()).list().isEmpty()) {
                            getSession().save(rynek);
                            System.out.println("MARKET ADDED: " + rynek.getSpecificMarket().getName());
                        }

                        tx.commit();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    } finally {
                        getSession().close();
                    }

                }
            }
        }
    }

    public void soccerGamesUpdate(Node currentNode) {
        League liga = new League();
        try {
            SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
            setSession(sessionFactory.openSession());
            Transaction tx = getSession().beginTransaction();
            Query q = getSession().createQuery("from Discipline where name = 'Pilka nozna'");
            setWynik((ArrayList) q.list());
            liga.setDiscipline((Discipline) getWynik().get(0));
            liga.setId(Integer.parseInt(currentNode.getAttributes().getNamedItem("IdLeague").getNodeValue()));
            liga.setName(currentNode.getAttributes().getNamedItem("Description").getNodeValue());
            if (getSession().createQuery(("from League where name = '" + liga.getName()) + "'").list().isEmpty()) {
                getSession().save(liga);
                System.out.println("LEAGUE ADDED: " + liga.getName());
            }

            tx.commit();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            getSession().close();
        }

        NodeList gameList = currentNode.getChildNodes();
        for (int j = 0; j <
                gameList.getLength(); j++) {
            Node currentGameNode = gameList.item(j);
            if (currentGameNode.getNodeType() == Node.ELEMENT_NODE) {
                Element elem = (Element) currentGameNode;
                try {
                    SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
                    setSession(sessionFactory.openSession());
                    Transaction tx = getSession().beginTransaction();
                    Game mecz = new Game();
                    Date data = new Date(getTagValue("date", elem));
                    mecz.setDate(data);
                    mecz.setName(getTagValue("hometeam", elem) + " - " + getTagValue("awayteam", elem));
                    Query q = getSession().createQuery("from League where name = '" + liga.getName() + "'");
                    setWynik((ArrayList) q.list());
                    mecz.setLeague((League) wynik.get(0));
                    if (getSession().createQuery(("from Game where name = '" + mecz.getName()) + "'").list().isEmpty()) {
                        getSession().save(mecz);
                        System.out.println("GAME ADDED: " + mecz.getName() + " " + mecz.getDate());
                    }

                    tx.commit();
                } catch (Exception ex) {
                    ex.printStackTrace();
                } finally {
                    getSession().close();
                }

                try {
                    SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
                    setSession(sessionFactory.openSession());
                    Transaction tx = getSession().beginTransaction();
                    Market rynek = new Market();
                    Query q = getSession().createQuery("from Game where name = '" + getTagValue("hometeam", elem) + " - " + getTagValue("awayteam", elem) + "'");
                    setWynik((ArrayList) q.list());
                    rynek.setGame((Game) wynik.get(0));
                    Double oddsDraw = convertOdds(getTagValue("DrawMoneyLine", elem));
                    Double oddsAway = convertOdds(getTagValue("AwayMoneyLine", elem));
                    Double oddsHome = convertOdds(getTagValue("HomeMoneyLine", elem));
                    rynek.setOdds_draw(oddsDraw);
                    rynek.setOdds_away(oddsAway);
                    rynek.setOdds_home(oddsHome);
                    rynek.setResult("n");
                    q =
                            getSession().createQuery("from specificMarket where name = '1x2'");
                    setWynik((ArrayList) q.list());
                    rynek.setSpecificMarket((specificMarket) wynik.get(0));
                    if (getSession().createQuery("select distinct m from Market m left join fetch m.game as g where g.id =" + rynek.getGame().getId()).list().isEmpty()) {
                        getSession().save(rynek);
                        System.out.println("MARKET ADDED: " + rynek.getSpecificMarket().getName());
                    }

                    tx.commit();
                } catch (Exception ex) {
                    ex.printStackTrace();
                } finally {
                    getSession().close();
                }

            }
        }
    }

    private static String getTagValue(String tag, Element elem) {
        NodeList list = elem.getElementsByTagName(tag).item(0).getChildNodes();
        Node value = (Node) list.item(0);

        if (value != null) {
            return value.getNodeValue();
        } else {
            return "0";
        }

    }

    private double convertOdds(String odds) {
        if (odds.equals("+100")) {
            return 2.0;
        } else if (odds.contains("+")) {
            return (Double.parseDouble(odds.substring(1)) + 100) / 100;
        } else if (odds.contains("-")) {
            return (100 / Double.parseDouble(odds.substring(1))) + 1;
        } else {
            return 0;
        }

    }

    private void betslipsUpdate(Market m) {
        try {
            SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
            setSession(sessionFactory.openSession());
            Transaction tx = getSession().beginTransaction();
            Betslip kupon = new Betslip();
            Query q = getSession().createQuery("from Betslip where marketID = " + m.getId() + " AND pending = 1");
            wynik.clear();
            setWynik((ArrayList) q.list());
            for (int i = 0; i <
                    wynik.size(); i++) {
                kupon = (Betslip) wynik.get(0);
                kupon.setPending(false);
                if (kupon.getSelection().equals(m.getResult())) {
                    kupon.setWon(true);
                    double wygrana = kupon.getStake() * kupon.getOdds();
                    Transact transakcja = new Transact();
                    transakcja.creditWonBetslip(wygrana, kupon.getBettor());
                } else {
                    kupon.setWon(false);
                }

                getSession().update(kupon);
            }

            tx.commit();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    public void downloadFile(String address, String filename) {
        try {
            URL url = new URL(address);
            BufferedInputStream in = new BufferedInputStream(url.openStream());
            FileOutputStream fout = new FileOutputStream(filename);
            BufferedOutputStream bout = new BufferedOutputStream(fout, 1024);
            byte data[] = new byte[1024];
            int bytesRead = 0;
            while ((bytesRead = in.read(data)) != -1) {
                String part = new String(data, 0, bytesRead);
                bout.write(part.getBytes());
            }
            bout.flush();
            bout.close();
            fout.close();
            in.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * @return the session
     */
    public Session getSession() {
        return session;
    }

    /**
     * @param session the session to set
     */
    public void setSession(Session session) {
        this.session = session;
    }

    /**
     * @return the wynik
     */
    public List getWynik() {
        return wynik;
    }

    /**
     * @param wynik the wynik to set
     */
    public void setWynik(List wynik) {
        this.wynik = wynik;
    }

    public void run() {
        int k = 0;
        while (true) {
            System.out.println(k++);
            gamesUpdate();
            scoresUpdate();
            try {
                Thread.sleep(30000);
            } catch (Exception ex) {
                System.out.println("Exception " + ex);
            }
        }
    }
}
